import 'dart:async';
import 'dart:io';
import 'package:another_flushbar/flushbar.dart';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:city_pickers/city_pickers.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_picker_plus/flutter_picker_plus.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:photo_view/photo_view.dart';
import 'package:webview_flutter/webview_flutter.dart';

class MyIconButton extends StatelessWidget {
  final Widget image;
  final String name;
  final onPressed;

  MyIconButton(this.image, this.name, {this.onPressed});

  @override
  Widget build(BuildContext context) {
    return InkWell(
        onTap: onPressed,
        child: Column(mainAxisSize: MainAxisSize.min, children: [
          image,
          SizedBox(height: 6),
          Text(name, style: TextStyle(fontSize: 12))
        ]));
  }
}

class MySliverDelegate extends SliverPersistentHeaderDelegate {
  MySliverDelegate({
    @required this.minHeight,
    @required this.maxHeight,
    @required this.child,
  });

  final double? minHeight; //最小高度
  final double? maxHeight; //最大高度
  final Widget? child; //子Widget布局

  @override
  double get minExtent => minHeight!;

  @override
  double get maxExtent => maxHeight!;

  @override
  Widget build(BuildContext context, double shrinkOffset,
      bool overlapsContent) {
    return SizedBox.expand(child: child);
  }

  @override //是否需要重建
  bool shouldRebuild(MySliverDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}

class TextRadio extends StatelessWidget {
  final val;
  final text;
  final onChange;
  final globalVal;

  TextRadio({this.val, this.onChange, this.globalVal, this.text});

  @override
  Widget build(BuildContext context) {
    return Row(mainAxisSize: MainAxisSize.min, children: [
      Radio(value: val, groupValue: globalVal, onChanged: onChange),
      Text(text)
    ]);
  }
}

class NoFoundView extends StatelessWidget {
  final msg;

  const NoFoundView(this.msg);

  @override
  Widget build(BuildContext context) {
    return ListView(shrinkWrap: true, children: [
      const SizedBox(height: 200),
      Center(
          child: Text(
            msg,
            style: TextStyle(color: Colors.grey),
            textAlign: TextAlign.center,
          )),
      const SizedBox(height: 200),
    ]);
  }
}

class TextEditPage extends StatefulWidget {
  final title;
  final text;
  final reg;
  final maxLines;
  final maxLength;
  final labelText;
  final hintText;

  const TextEditPage(
      {Key? key, this.text, this.title, this.maxLines, this.maxLength, this.labelText, this.hintText, this.reg})
      : super(key: key);

  @override
  State createState() => _TextEditPageState();
}

class _TextEditPageState extends State<TextEditPage> {
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        actions: [
          TextButton(
              child: Text("保存"),
              onPressed: () {
                final form = _formKey.currentState;
                if (form!.validate()) {
                  form!.save();
                }
              })
        ],
        title: Text(widget.title),
      ),
      body: Container(
          padding: EdgeInsets.all(10),
          child: Form(
              key: _formKey,
              child: TextFormField(
                  initialValue: widget.text ?? null,
                  textInputAction: TextInputAction.done,
                  maxLines: widget.maxLines ?? 1,
                  maxLength: widget.maxLength ?? null,
                  autofocus: true,
                  onSaved: (val) {
                    Navigator.pop(context, val);
                  },
                  validator: (val) {
                    if (val == "") return "不能为空";
                    if (widget.reg != null) {
                      if (RegExp(widget.reg).hasMatch(val!)) {
                        return null;
                      } else {
                        return "格式不正确";
                      }
                    } else {
                      return null;
                    }
                  },
                  decoration: InputDecoration(
                      labelText: widget.labelText ?? null,
                      labelStyle: TextStyle(color: Colors.orange),
                      hintText: widget.hintText ?? null,
                      hintStyle: TextStyle(fontSize: 12, color: Colors.grey),
                      focusedBorder: UnderlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.black,
                        ),
                      )))))
    );
  }
}

class CoolDownButton extends StatefulWidget {
  final onPressed;
  final validator;

  CoolDownButton({this.onPressed, this.validator});

  @override
  _CoolDownButtonState createState() => _CoolDownButtonState();
}

class _CoolDownButtonState extends State<CoolDownButton> {
  Timer? countDownTimer;
  int sec = 0;
  bool isCD = false;
  String buttonText = "获取验证码";

  @override
  void deactivate() {
    if (countDownTimer != null) countDownTimer!.cancel();
    super.deactivate();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialButton(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(28),
      ),
      color: Colors.black,
      elevation: 0,
      onPressed: isCD ? null : onPressed,
      child:
      Text(buttonText, style: isCD ? null : TextStyle(color: Colors.white)),
    );
  }

  onPressed() async {
    if (isCD) {
      return;
    }
    if (widget.validator() == null) {
      var res = await widget.onPressed();
      if (res) {
        coolDownTimer();
      }
    } else {
      EasyLoading.showToast(widget.validator());
    }
  }

  coolDownTimer() {
    sec = 60;
    isCD = true;
    countDownTimer = Timer.periodic(Duration(seconds: 1), (timer) {
      if (sec > 1) {
        sec--;
        buttonText = "${sec}S";
      } else {
        isCD = false;
        buttonText = "重新发送";
        countDownTimer!.cancel();
      }
      setState(() {});
    });
  }
}

class GlobalImageView extends StatelessWidget {
  final String imgUrl;
  final double height;
  final double width;
  final double radius;
  final fit;

  GlobalImageView(this.imgUrl,
      {required this.height,
        required this.width,
        this.radius = 8,
        this.fit = BoxFit.cover});

  @override
  Widget build(BuildContext context) {
    return CachedNetworkImage(
        imageUrl: imgUrl,
        fadeInDuration: Duration(milliseconds: 0),
        fadeOutDuration: Duration(milliseconds: 0),
        imageBuilder: (context, imageProvider) =>
            Container(
              width: width,
              height: height,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(radius),
                image: DecorationImage(
                    image: imageProvider,
                    fit: fit,
                    alignment: Alignment.topCenter),
              ),
            ),
        errorListener: (v) {
          print("图片加载失败:$imgUrl");
        },
        placeholder: (context, url) => defaultView(width, height, radius),
        errorWidget: (context, url, error) =>
            defaultView(width, height, radius));
  }
}

Widget defaultView(width, height, radius) {
  return Container(
    width: width,
    height: height,
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(radius),
      color: Color(0xffeeeeee),
    ),
  );
}

Future<String> bootTime(BuildContext context, DateTime startTime,
    DateTime endTime) async {
  endTime = endTime.add(Duration(days: 1));
  var res;
  await Picker(
      adapter: DateTimePickerAdapter(
        customColumnType: [2, 3, 4],
        minValue: startTime,
        maxValue: endTime,
        value: startTime,
        minuteInterval: 20,
        yearSuffix: "年",
        monthSuffix: "月",
        daySuffix: "日",
      ),
      delimiter: [
        PickerDelimiter(
            column: 2,
            child: Container(
              alignment: Alignment.center,
              padding: EdgeInsets.fromLTRB(12, 0, 8, 0),
              child: Text(':',
                  style:
                  TextStyle(fontWeight: FontWeight.bold, fontSize: 14)),
              color: Colors.white,
            )),
      ],
      title: Text("选择预计时间"),
      onConfirm: (Picker picker, List value) {
        res = picker.adapter.text.substring(0, 19);
      },
      cancelText: "取消",
      confirmText: "确定")
      .showModal(context);
  return res;
}

class PhotoViewWidget extends StatelessWidget {
  final imgUrl;

  PhotoViewWidget(this.imgUrl);

  @override
  Widget build(BuildContext context) {
    return Container(child: PhotoView(imageProvider: NetworkImage(imgUrl)));
  }
}

void showBottomDialog(context, child) {
  showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      builder: (c) {
        return AnimatedPadding(
            padding: MediaQuery
                .of(context)
                .viewInsets,
            duration: Duration(milliseconds: 100),
            child: child);
      });
}

class TooltipShape extends ShapeBorder {
  TooltipShape();

  final BorderSide _side = BorderSide.none;
  final BorderRadiusGeometry _borderRadius = BorderRadius.zero;

  @override
  EdgeInsetsGeometry get dimensions =>
      EdgeInsets.all(
        _side.width,
      );

  @override
  Path getInnerPath(Rect rect, {
    TextDirection? textDirection,
  }) {
    final Path path = Path();

    path.addRRect(
      _borderRadius.resolve(textDirection).toRRect(rect).deflate(_side.width),
    );

    return path;
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    final Path path = Path();
    final RRect rrect = _borderRadius.resolve(textDirection).toRRect(rect);

    path.moveTo(0, 10);
    path.quadraticBezierTo(0, 0, 10, 0);
    path.lineTo(rrect.width / 2 - 10, 0);
    path.lineTo(rrect.width / 2, -10);
    path.lineTo(rrect.width / 2 + 10, 0);
    path.quadraticBezierTo(rrect.width, 0, rrect.width, 10);
    path.lineTo(rrect.width, rrect.height - 10);
    path.quadraticBezierTo(
        rrect.width, rrect.height, rrect.width - 10, rrect.height);
    path.lineTo(10, rrect.height);
    path.quadraticBezierTo(0, rrect.height, 0, rrect.height - 10);
    return path;
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {}

  @override
  ShapeBorder scale(double t) =>
      RoundedRectangleBorder(
        side: _side.scale(t),
        borderRadius: BorderRadius.circular(4),
      );
}

class WebViewPage extends StatelessWidget {
  final bannerDetailUrl;
  final bannerName;

  WebViewPage(this.bannerDetailUrl, this.bannerName);

  @override
  Widget build(BuildContext context) {
    var controller = WebViewController();
    controller.loadRequest(Uri.parse(bannerDetailUrl));
    return Scaffold(
        appBar: AppBar(
          title: Text(bannerName),
          centerTitle: true,
        ),
        body: WebViewWidget(controller: controller));
  }
}

void showGlobalFlushBar(BuildContext context, String title, String message) {
  Flushbar(
    onTap: (v) {
      Navigator.pop(context);
    },
    margin: EdgeInsets.all(16),
    borderRadius: BorderRadius.circular(12),
    flushbarPosition: FlushbarPosition.TOP,
    flushbarStyle: FlushbarStyle.FLOATING,
    reverseAnimationCurve: Curves.decelerate,
    forwardAnimationCurve: Curves.elasticOut,
    backgroundColor: Color.fromRGBO(180, 180, 180, 1),
    isDismissible: false,
    duration: Duration(seconds: 6),
    showProgressIndicator: false,
    titleText: Text(
      title,
      style: TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 14.0,
        color: Color.fromRGBO(58, 58, 58, 1),
      ),
    ),
    messageText: Text(
      message,
      style: TextStyle(
        fontSize: 14.0,
        color: Color.fromRGBO(58, 58, 58, 1),
      ),
    ),
  ).show(context);
}

Future<bool> getPermission(BuildContext context, Permission permission,
    String title, String message) async {
  var status = await permission.status;
  if (status == PermissionStatus.granted) {
    return true;
  } else {
    showGlobalFlushBar(context, title, message);
    status = await permission.request();
    if (status == PermissionStatus.granted) {
      return true;
    } else {
      return false;
    }
  }
}

Future<bool> checkGalleryPermission(BuildContext context) async {
  bool hasPermission = true;
  String title = "外卖猿想访问你的媒体文件";
  String message = "为了您能正常分享图片/视频，保存图片/视频，外卖猿需要申请储存权限。\n如您拒绝授权，不影响您使用APP的其他功能";
  final androidInfo = await DeviceInfoPlugin().androidInfo;
  if (androidInfo.version.sdkInt <= 32) {
    hasPermission =
    await getPermission(context, Permission.storage, title, message);
  } else {
    hasPermission =
    await getPermission(context, Permission.photos, title, message);
  }
  return hasPermission;
}

Future<String> getImgByGallery(BuildContext context, {isCrop = false}) async {
  if (Platform.isAndroid) {
    bool hasPermission = await checkGalleryPermission(context);
    if (!hasPermission) {
      return "";
    }
  }
  try {
    final file = await ImagePicker().pickImage(
        source: ImageSource.gallery,
        imageQuality: 80,
        maxHeight: 512,
        maxWidth: 512);
    if (file == null) return "";
    if (isCrop) {
      return cropFile(context, File(file.path));
    } else {
      return file.path;
    }
  } catch (e) {
    return "";
  }
}

Future<String> getImgByCamera(BuildContext context, {isCrop = false}) async {
  if (Platform.isAndroid) {
    bool hasPermission = await getPermission(
        context,
        Permission.camera,
        "外卖猿想访问你的相机",
        "为了您能正常体验拍照、录制视频、扫码等功能，外卖猿需要申请相机权限。\n如您拒绝授权，不影响您使用APP的其他功能");
    if (!hasPermission) {
      return "";
    }
  }
  final file = await ImagePicker().pickImage(
      source: ImageSource.camera,
      imageQuality: 80,
      maxHeight: 512,
      maxWidth: 512);
  if (file == null) return "";
  if (isCrop) {
    return cropFile(context, File(file.path));
  } else {
    return file.path;
  }
}

Future<List<XFile>> getMultiImage(BuildContext context) async {
  if (Platform.isAndroid) {
    bool hasPermission = await checkGalleryPermission(context);
    if (!hasPermission) {
      return [];
    }
  }
  final ImagePicker _picker = ImagePicker();
  final List<XFile>? images = await _picker.pickMultiImage(
      imageQuality: 80, maxHeight: 512, maxWidth: 512);
  return images!;
}

Future<String> cropFile(BuildContext context, File file) async {
  ImageCropper ic = ImageCropper();
  CroppedFile? croppedFile = await ic.cropImage(
      sourcePath: file.path,
      compressQuality: 10,
      aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1),
      uiSettings: [
        AndroidUiSettings(
            toolbarTitle: '裁剪',
            toolbarColor: Colors.deepOrange,
            toolbarWidgetColor: Colors.white,
            initAspectRatio: CropAspectRatioPreset.original,
            lockAspectRatio: false),
        IOSUiSettings(
          title: '裁剪',
        ),
        WebUiSettings(
          context: context,
        ),
      ]);
  if (croppedFile != null) {
    return croppedFile.path;
  }
  return '';
}

Future<String> getVideo(BuildContext context, {isCamera = false}) async {
  var file;
  final picker = ImagePicker();
  var pickedFile = await picker.pickVideo(
      source: isCamera ? ImageSource.camera : ImageSource.gallery);
  file = File(pickedFile!.path);
  if (file == null) {
    return "";
  }
  return pickedFile.path;
}

Widget uploadButton(name, imgUrl,
    {height = 80.0, width = 80.0, isLocal = false}) {
  return imgUrl == null || imgUrl == "" || imgUrl == "http://"
      ? Container(
      height: height,
      width: width,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8.0),
        color: const Color(0xfff3f3f3),
      ),
      child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
        Icon(Icons.camera_alt, color: Colors.grey),
        Text(
          name,
          style: const TextStyle(
            fontSize: 12,
            color: Color(0xff222222),
          ),
          textAlign: TextAlign.center,
        )
      ]))
      : Container(
    height: height,
    width: width,
    decoration: BoxDecoration(
        image: isLocal
            ? DecorationImage(
            image: FileImage(File(imgUrl)), fit: BoxFit.fitWidth)
            : DecorationImage(
            image: NetworkImage(imgUrl), fit: BoxFit.fitWidth)),
  );
}

void pickSex(BuildContext context) {
  Picker(
      adapter: NumberPickerAdapter(data: [
        NumberPickerColumn(
            begin: 0,
            end: 1,
            onFormatValue: (v) {
              return v == 0 ? "男" : "女";
            }),
      ]),
      title: Text("营业状态"),
      onConfirm: (Picker picker, List value) {
        print(value.toString());
        print(picker.getSelectedValues());
      },
      cancelText: "取消",
      confirmText: "确定")
      .showModal(context);
}

void showAlertPopup(BuildContext context, String detail,
    {String? title}) async {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (context) =>
        AlertDialog(
          title: title != null ? Text(title) : null,
          content: Text(detail),
          actions: [
            TextButton(
                child: Text('关闭'),
                onPressed: () {
                  Navigator.pop(context);
                }),
          ],
        ),
  );
}

Future<bool> confirmPopup(BuildContext context, String title) async {
  var res = await showDialog(
    context: context,
    barrierDismissible: false,
    builder: (context) =>
        AlertDialog(
          title: Text(title),
          actions: [
            TextButton(
                child: Text('我再想想', style: TextStyle(color: Colors.grey)),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
            TextButton(
                child: Text('确定'),
                onPressed: () {
                  Navigator.pop(context, true);
                }),
          ],
        ),
  );
  return res;
}

// void pickDate(BuildContext context) {
//   var picker = Picker(
//       adapter: new DateTimePickerAdapter(
//         customColumnType: [0, 1, 2],
//       ),
//       title: new Text("你的生日"),
//       selectedTextStyle: TextStyle(color: Theme.of(context).accentColor),
//       onConfirm: (Picker picker, List value) {
//         print((picker.adapter as DateTimePickerAdapter).value);
//       },
//       cancelText: "取消",
//       cancelTextStyle: TextStyle(color: Theme.of(context).accentColor),
//       confirmText: "确定",
//       confirmTextStyle: TextStyle(color: Theme.of(context).accentColor));
//
//   showModalBottomSheet(
//       context: context,
//       backgroundColor: Colors.transparent,
//       builder: (context) {
//         return Container(
//           color: Colors.white,
//           child: picker.makePicker(null, true),
//         );
//       });
// }
//
Future<Result> pickCity(BuildContext context) async {
  Result? result = await CityPickers.showCitiesSelector(
    context: context,
  );
  return result!;
}

void showPickerTimeRange(context,
    title,
    beginTime,
    endTime,
    onConfirm,) {
  var startH = int.parse(beginTime.split(":")[0]);
  var startM = int.parse(beginTime.split(":")[1]);
  var endH = int.parse(endTime.split(":")[0]);
  var endM = int.parse(endTime.split(":")[1]);
  final range = <DateTime>[
    DateTime(0, 1, 1, startH, startM),
    DateTime(0, 1, 1, endH, endM)
  ];
  final p1 = Picker(
      adapter: DateTimePickerAdapter(
          type: PickerDateTimeType.kHM, value: range[0], minuteInterval: 20),
      delimiter: [
        PickerDelimiter(
            column: 0,
            child: Container(
              alignment: Alignment.center,
              width: 80,
              padding: EdgeInsets.fromLTRB(12, 0, 8, 0),
              child: Text('开始',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)),
              color: Colors.white,
            )),
      ],
      onSelect: (Picker picker, int index, List<int> selected) {
        String text =
        (picker.adapter as DateTimePickerAdapter).value.toString();
        beginTime = "${text.substring(11, 13)}:${text.substring(14, 16)}";
      },
      title: Text(title),
      onConfirm: (picker, selected) {
        onConfirm(beginTime, endTime);
      });
  final p2 = Picker(
      adapter: DateTimePickerAdapter(
          type: PickerDateTimeType.kHM, value: range[1], minuteInterval: 20),
      hideHeader: true,
      delimiter: [
        PickerDelimiter(
            column: 0,
            child: Container(
              alignment: Alignment.center,
              padding: EdgeInsets.fromLTRB(12, 0, 8, 0),
              width: 80,
              child: Text('结束',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)),
              color: Colors.white,
            )),
      ],
      onSelect: (Picker picker, int index, List<int> selected) {
        String text =
        (picker.adapter as DateTimePickerAdapter).value.toString();
        endTime = "${text.substring(11, 13)}:${text.substring(14, 16)}";
      });

  showModalBottomSheet(
      context: context,
      builder: (context) {
        return Column(
            mainAxisSize: MainAxisSize.min,
            children: [p1.makePicker(), p2.makePicker()]);
      });
}

void showPickerDateRange(context,
    title,
    beginTime,
    endTime,
    onConfirm,) {
  List beginDate = beginTime.split("-");
  List endDate = endTime.split("-");
  final range = <DateTime>[
    DateTime(int.parse(beginDate[0]), int.parse(beginDate[1]),
        int.parse(beginDate[2]), 0, 0),
    DateTime(int.parse(endDate[0]), int.parse(endDate[1]),
        int.parse(endDate[2]), 0, 0)
  ];
  final p1 = Picker(
      adapter: DateTimePickerAdapter(
          isNumberMonth: true,
          type: PickerDateTimeType.kYMD,
          value: range[0],
          minuteInterval: 20),
      delimiter: [
        PickerDelimiter(
            column: 0,
            child: Container(
              alignment: Alignment.center,
              width: 80,
              padding: EdgeInsets.fromLTRB(12, 0, 8, 0),
              child: Text('开始',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)),
              color: Colors.white,
            )),
      ],
      onSelect: (Picker picker, int index, List<int> selected) {
        String text =
        (picker.adapter as DateTimePickerAdapter).value.toString();
        beginTime = text.substring(0, 11);
      },
      title: Text(title),
      onConfirm: (picker, selected) {
        onConfirm(beginTime, endTime);
      });
  final p2 = Picker(
      adapter: DateTimePickerAdapter(
          isNumberMonth: true,
          type: PickerDateTimeType.kYMD,
          value: range[1],
          minuteInterval: 20),
      hideHeader: true,
      delimiter: [
        PickerDelimiter(
            column: 0,
            child: Container(
              alignment: Alignment.center,
              padding: EdgeInsets.fromLTRB(12, 0, 8, 0),
              width: 80,
              child: Text('结束',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)),
              color: Colors.white,
            )),
      ],
      onSelect: (Picker picker, int index, List<int> selected) {
        String text =
        (picker.adapter as DateTimePickerAdapter).value.toString();
        endTime = text.substring(0, 11);
      });

  showModalBottomSheet(
      context: context,
      builder: (context) {
        return Column(
            mainAxisSize: MainAxisSize.min,
            children: [p1.makePicker(), p2.makePicker()]);
      });
}

Future showPickPicDialog(context) async {
  var res = await showModalBottomSheet(
      backgroundColor: Colors.transparent,
      isScrollControlled: true,
      context: context,
      builder: (c) {
        return AnimatedPadding(
            padding: MediaQuery
                .of(context)
                .viewInsets,
            duration: const Duration(milliseconds: 100),
            child: Container(
                decoration: const BoxDecoration(
                    borderRadius: BorderRadius.horizontal(
                        left: Radius.circular(12), right: Radius.circular(12)),
                    color: Colors.white),
                child: Column(mainAxisSize: MainAxisSize.min, children: [
                  ListTile(
                      title: const Center(child: Text("拍摄")),
                      onTap: () async {
                        String path = await getImgByCamera(context);
                        if (path != "") Navigator.pop(context, [XFile(path)]);
                      }),
                  const Divider(height: 1),
                  ListTile(
                      title: const Center(child: Text("从相册选择")),
                      onTap: () async {
                        List files = await getMultiImage(context);
                        Navigator.pop(context, files);
                      }),
                  Container(color: const Color(0xffeeeeee), height: 10),
                  ListTile(
                      dense: true,
                      title: const Center(child: Text("取消")),
                      onTap: () {
                        Navigator.pop(context);
                      }),
                ])));
      });
  return res;
}

void showPhoto(BuildContext context, String img_url) {
  if (img_url == "" || img_url == null) {
    return;
  }
  showDialog(
      context: context,
      builder: (c) {
        return InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: CachedNetworkImage(
                imageUrl: img_url,
                fadeInDuration: const Duration(milliseconds: 100),
                imageBuilder: (context, imageProvider) =>
                    PhotoView(
                        minScale: PhotoViewComputedScale.contained * 0.8,
                        maxScale: PhotoViewComputedScale.covered * 1.8,
                        imageProvider: imageProvider,
                        loadingBuilder: (x, e) {
                          return const Center(
                              child: CircularProgressIndicator(
                                  strokeWidth: 2, color: Colors.white));
                        }),
                placeholder: (context, url) =>
                const Center(
                    child: CircularProgressIndicator(
                        strokeWidth: 2, color: Colors.white)),
                errorWidget: (context, url, error) =>
                const Center(child: Text("图片加载失败"))));
      });
}

class SelectPic extends StatefulWidget {
  final Function(List<String> value) onCallback;

  const SelectPic({super.key, required this.onCallback});

  @override
  State<SelectPic> createState() => _SelectPicState();
}

class _SelectPicState extends State<SelectPic>
    with AutomaticKeepAliveClientMixin {
  List<String> pics = [];

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return Wrap(runSpacing: 10, spacing: 10, children: [
      Wrap(
          runSpacing: 10,
          spacing: 10,
          children: pics
              .map((e) =>
              Stack(children: [
                Container(
                    width: 80,
                    height: 80,
                    decoration: BoxDecoration(
                      image: DecorationImage(
                          image: FileImage(File(e)), fit: BoxFit.cover),
                      borderRadius: BorderRadius.circular(8.0),
                    )),
                Positioned(
                    right: 0,
                    top: 0,
                    child: InkWell(
                        onTap: () {
                          setState(() {
                            pics.remove(e);
                            widget.onCallback(pics);
                          });
                        },
                        child: const Icon(Icons.highlight_remove,
                            color: Colors.white)))
              ]))
              .toList()),
      InkWell(onTap: uploadImg, child: uploadButton("${pics.length}/9", "")),
    ]);
  }

  uploadImg() async {
    var res = await showPickPicDialog(context);
    List files = res ?? [];
    if ((pics.length + files.length) > 9) {
      EasyLoading.showToast("最多9张图片");
      return;
    }
    for (XFile file in files) {
      pics.add(file.path);
    }
    widget.onCallback(pics);
    setState(() {});
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

class SendDialog extends StatefulWidget {
  final List<String> pics;
  final Function(String path, Function(double sent, double total)) uploadFile;

  const SendDialog({
    super.key,
    required this.uploadFile,
    required this.pics,
  });

  @override
  State<SendDialog> createState() => _SendDialogState();
}

class _SendDialogState extends State<SendDialog> {
  double percent = 0.0;
  List<String> imgUrls = [];

  @override
  void initState() {
    sendData();
    super.initState();
  }

  sendData() async {
    for (String path in widget.pics) {
      var res = await widget.uploadFile(path, (sent, total) {
        setState(() {
          percent = sent / total;
        });
      });
      if (res["errcode"] == 0) {
        imgUrls.add(res["img_url"]);
      }
    }
    Navigator.pop(context, imgUrls);
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
        scrollable: true,
        content: Container(
            padding: EdgeInsets.all(16), child: Center(child: sending())));
  }

  sending() {
    return Column(mainAxisSize: MainAxisSize.min, children: [
      SizedBox(
          width: 80,
          height: 80,
          child: Stack(children: [
            SizedBox(
                width: 80,
                height: 80,
                child: CircularProgressIndicator(
                  strokeWidth: 10,
                  value: percent,
                  backgroundColor: const Color(0xffeeeeee),
                  valueColor: const AlwaysStoppedAnimation<Color>(Colors.black),
                )),
            Align(
                alignment: Alignment.center,
                child: Text("${(percent * 100).toStringAsFixed(0)}%",
                    style: TextStyle(fontSize: 22)))
          ])),
      SizedBox(height: 24),
      Text("上传图片", style: TextStyle(fontSize: 22)),
    ]);
  }

  sendSuccess() {
    return const Column(mainAxisSize: MainAxisSize.min, children: [
      Icon(Icons.check_circle, color: Colors.green, size: 100),
      SizedBox(height: 14),
      Text("Yeah! 上传成功", style: TextStyle(fontSize: 22)),
      SizedBox(height: 24),
      Text("2秒后关闭", style: TextStyle(color: Colors.grey))
    ]);
  }
}
